/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tpgen.grammar;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 *
 * @author shanki
 */
public class Alt implements Symbol {
    private List<Pair> symbols  = new ArrayList<Pair>();

    @Override
    public boolean isUsable() {
        
        for (Pair pair : symbols) {
            if (pair.isUsable()) {
                return true;
            }
        }
        
        return false;
    }    
    
    public Alt add(Symbol symbol, double prob) {
        symbols.add(new Pair(symbol, prob));
        
        return this;
    }

    @Override
    public Collection<Symbol> expand(Context context) {
        double p    = context.nextDouble();
        double psum = 0;
        
        for (Pair pair : symbols) {
            if (pair.isUsable()) {
                psum += pair.prob;

                if (p <= psum) {
                    List<Symbol> sym = new ArrayList<Symbol>();
                    sym.add(pair.symbol);
                    return sym;
                }
            }
        }
        
        List<Symbol> sym = new ArrayList<Symbol>();
        Pair last = symbols.get(symbols.size() - 1);
        sym.add(last.symbol);
        return sym;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Alt) {
            return symbols.equals(((Alt)obj).symbols);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 83 * hash + (this.symbols != null ? this.symbols.hashCode() : 0);
        return hash;
    }

    @Override
    public String toString() {
        return "/alt/";
    }    

    @Override
    public String toUserString() {
        return "";
    }
    
    public void setOnetoUniformPropability() {
        // one propabilities are changed to uniform, others stay as are
        int size = 0;
        
        for (Pair pair : symbols) {
            if (pair.isUsable() && pair.prob == 1) {
                ++size;
            }
        }
        
        if (size > 0) {                        
            
            double prop = 1.0 / size;
            
            for (Pair pair : symbols) {
                if (pair.isUsable() && pair.prob == 1) {
                    pair.prob = prop;
                }
            }
        }
    }

    private static class Pair {
        private Symbol symbol;
        private double prob;

        public Pair(Symbol symbol, double prob) {
            this.symbol = symbol;
            this.prob   = prob;
        }
        
        public boolean isUsable() {
            return prob > 0 && symbol.isUsable();
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof Pair) {
                Pair other = (Pair) obj;
                
                return  this.symbol.equals(other.symbol) &&
                        this.prob == other.prob;
            } else {
                return false;
            }
        }

        @Override
        public int hashCode() {
            int hash = 5;
            hash = 79 * hash + (this.symbol != null ? this.symbol.hashCode() : 0);
            hash = 79 * hash + (int) (Double.doubleToLongBits(this.prob) ^ (Double.doubleToLongBits(this.prob) >>> 32));
            return hash;
        }
        
        
        
    }
}
